package com.kami.common.util;

import static com.kami.common.util.StringUtil.lineToHump;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ObjectUtils;
import org.apache.velocity.VelocityContext;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;;

public class MybatisGeneratorUtil {
	
	// generatorConfig模板路径
	private static String generatorConfig_vm = "src/main/resources/template/generatorConfig.vm";
	// Service模板路径
	private static String service_vm = "src/main/resources/template/service.java.vm";
	// ServiceImpl模版路径
	private static String serviceImpl_vm = "src/main/resources/template/serviceImpl.java.vm";
	// controller 模板路径
	private static String controller_vm = "src/main/resources/template/controller.java.vm";
	
	/**
	 * 根据模板生成generatorConfig.xml文件
	 * @param jdbc_driver   驱动路径
	 * @param jdbc_url      链接
	 * @param jdbc_username 帐号
	 * @param jdbc_password 密码
	 * @param module        项目模块
	 * @param database      数据库
	 * @param table_prefix  表前缀
	 * @param package_name  包名
	 */
	public static void generator(
			String jdbc_driver,
			String jdbc_url,
			String jdbc_username,
			String jdbc_password,
			String module,
			String database,
			String table_prefix,
			String package_name,
			Map<String, String> last_insert_id_tables) throws Exception{
		String relativelyPath=System.getProperty("user.dir");
		System.out.println(relativelyPath);
		String targetProject = "";//
		String path = "src/main/resources/generatorConfig.xml";
		String sql = "SELECT table_name,table_comment FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = '" + database + "' AND table_name LIKE '" + table_prefix + "_%';";
		
		System.out.println("========== 开始生成generatorConfig.xml文件 ==========");
		List<Map<String, Object>> tables = new ArrayList<>();
		try {
			VelocityContext context = new VelocityContext();
			Map<String, Object> table;

			// 查询定制前缀项目的所有表
			JdbcUtil jdbcUtil = new JdbcUtil(jdbc_driver, jdbc_url, jdbc_username, jdbc_password);
			List<Map> result = jdbcUtil.selectByParams(sql, null);
			for (Map map : result) {
				System.out.println(map.get("TABLE_NAME"));
				table = new HashMap<>();
				table.put("table_name", map.get("TABLE_NAME"));
				table.put("model_name", lineToHump(ObjectUtils.toString(map.get("TABLE_NAME"))));
				table.put("table_comment", map.get("TABLE_COMMENT"));
				tables.add(table);
			}
			jdbcUtil.release();

			String targetProject_sqlMap =  "" ;
			context.put("tables", tables);
			context.put("generator_javaModelGenerator_targetPackage", package_name + ".entity");
			context.put("generator_sqlMapGenerator_targetPackage", "mapper");
			context.put("generator_javaClientGenerator_targetPackage", package_name + ".dao");
			context.put("targetProject", targetProject);
//			context.put("targetProject_sqlMap", targetProject_sqlMap);
			context.put("generator_jdbc_password", jdbc_password);
			context.put("last_insert_id_tables", last_insert_id_tables);
			VelocityUtil.generate(generatorConfig_vm, path, context);
			// 删除旧代码
			deleteDir(new File(targetProject + "src/main/java/" + package_name.replaceAll("\\.", "/") + "/entity"));
			deleteDir(new File(targetProject + "src/main/resources/mapper/"));
			deleteDir(new File(targetProject_sqlMap + "src/main/java/" + package_name.replaceAll("\\.", "/") + "/dao"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("========== 结束生成generatorConfig.xml文件 ==========");

		System.out.println("========== 开始运行MybatisGenerator ==========");
		List<String> warnings = new ArrayList<>();
		File configFile = new File(path);
		ConfigurationParser cp = new ConfigurationParser(warnings);
		Configuration config = cp.parseConfiguration(configFile);
		DefaultShellCallback callback = new DefaultShellCallback(true);
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		myBatisGenerator.generate(null);
		for (String warning : warnings) {
			System.out.println(warning);
		}
		System.out.println("========== 结束运行MybatisGenerator ==========");
		
		System.out.println("========== 开始生成Service和controller ==========");
		String date = new SimpleDateFormat("yyyy/M/d").format(new Date());
		String servicePath = targetProject + "src/main/java/" + package_name.replaceAll("\\.", "/") + "/service";
		String serviceImplPath = targetProject + "src/main/java/" + package_name.replaceAll("\\.", "/") + "/service/impl";
		String controllerPath = targetProject + "src/main/java/" + package_name.replaceAll("\\.", "/") + "/controller";
		String superServiceClass = "BaseService";
		String superServiceImplClass = "BaseServiceImpl";
		String superServiceClassPackage = "com.kami.common.base.BaseService";
		String superServiceClassImplPackage = "com.kami.common.base.BaseServiceImpl";
		String superControllerClass = "BaseController";
		String superControllerClassPackage = "com.kami.common.base.BaseController";
		String author = "Mr jiang";
		mkdir(servicePath);
		mkdir(serviceImplPath);
		mkdir(controllerPath);
		for (int i = 0; i < tables.size(); i++) {
			String entity = lineToHump(ObjectUtils.toString(tables.get(i).get("table_name")));
			// 生成 Service
			String service = servicePath + "/" + entity + "Service.java";
			String serviceImpl = serviceImplPath + "/" + entity + "ServiceImpl.java";
			String controller = controllerPath + "/" + entity + "Controller.java";
			File serviceFile = new File(service);
			if (!serviceFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("comment", tables.get(i).get("table_comment"));
				context.put("author", author);
				context.put("date", date);
				context.put("package", package_name);
				context.put("entity", entity);
				context.put("superServiceClassPackage", superServiceClassPackage);
				context.put("superServiceClass", superServiceClass);
				VelocityUtil.generate(service_vm, service, context);
			}
			//serviceImpl
			File serviceImplFile = new File(serviceImpl);
			if (!serviceImplFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("comment", tables.get(i).get("table_comment"));
				context.put("author", author);
				context.put("date", date);
				context.put("package", package_name);
				context.put("entity", entity);
				context.put("superServiceClassPackage", superServiceClassPackage);
				context.put("superServiceImplClassPackage", superServiceClassImplPackage);
				context.put("superServiceImplClass", superServiceImplClass);
				VelocityUtil.generate(serviceImpl_vm, serviceImpl, context);
			}
			//controller
			File controllerFile = new File(controller);
			String mapping = ObjectUtils.toString(tables.get(i).get("table_name")).toLowerCase().replace("_", "/");
			if (!controllerFile.exists()) {
				VelocityContext context = new VelocityContext();
				context.put("comment", tables.get(i).get("table_comment"));
				context.put("mapping", mapping);
				context.put("author", author);
				context.put("date", date);
				context.put("package", package_name);
				context.put("entity", entity);
				context.put("entityToLowerCaseFirstOne", StringUtil.toLowerCaseFirstOne(entity));
				context.put("superServiceClassPackage", superServiceClassPackage);
				context.put("superServiceImplClassPackage", superServiceClassImplPackage);
				context.put("superServiceImplClass", superServiceImplClass);
				context.put("superControllerClassPackage", superControllerClassPackage);
				context.put("superControllerClass", superControllerClass);
				VelocityUtil.generate(controller_vm, controller, context);
				
			}
			
		}
		System.out.println("========== 结束生成Service和controller ==========");
		
	}
	
	// 创建文件夹
	private static void mkdir(String servicePath) {
		File file = new File(servicePath);
		if (!file.exists()) {
			file.mkdirs();
		}
	}

	// 递归删除非空文件夹
	public static void deleteDir(File dir) {
		if (dir.isDirectory()) {
			File[] files = dir.listFiles();
			for (int i = 0; i < files.length; i++) {
				deleteDir(files[i]);
			}
		}
		dir.delete();
	}

}
